import type { Ref } from 'vue'
import { nextTick, onMounted, ref, watch } from 'vue'
import type { MenuType as TabType } from '@/routers/type'

// route 路由对象
function useBar(tabs: Ref, emit: any, route: Ref, homePath: string) {
  // dom对象
  const tabsRef = ref<HTMLDivElement | null>(null) // 实际容器大小
  const tabsOutRef = ref<HTMLDivElement | null>(null) // 外侧容器对象
  const tabsOutWidth = ref<number>(0)
  const tabsWidth = ref<number>(0)
  const tabsTranlateLocation = ref<number>(0)
  const maxMoveDistance = ref<number>(0)
  const widthStep = 146
  const canMove = ref<boolean>(false)
  const activePath = ref<string[]>([])
  const defaultTab = {
    name: '首页',
    path: homePath,
    meta: {
      activeMenu: homePath,
    },
  }

  const calculateValue = () => {
    if (!tabsRef.value)
      return
    tabsWidth.value = tabsRef.value.clientWidth
    maxMoveDistance.value
      = tabsOutWidth.value < tabsWidth.value
        ? tabsOutWidth.value - tabsWidth.value
        : 0
    canMove.value = tabsWidth.value > tabsOutWidth.value
    if (!canMove.value && tabsTranlateLocation.value !== 0) {
      tabsTranlateLocation.value = 0
      tabsRef.value.style.left = '0px'
    }
  }

  const tabItemClick = (tab: TabType) => {
    activePath.value = [tab.path]
    emit('tabClick', tab)
  }

  const closeAllTab = (type: string) => {
    let leftTabs = []
    let removedTabs = []
    if (type === 'all') {
      tabItemClick(defaultTab)
      removedTabs = tabs.value
    }
    else {
      leftTabs = tabs.value.filter((per: TabType) =>
        activePath.value.includes(per.path),
      )
      removedTabs = tabs.value.filter(
        (per: TabType) => !activePath.value.includes(per.path),
      )
    }
    emit('removeTabs', removedTabs)
    emit('updateTabs', leftTabs)
    nextTick(calculateValue)
  }

  const translateX = (direction: string) => {
    let location = 0
    if (direction === 'pre') {
      location = tabsTranlateLocation.value + widthStep * 2
      tabsTranlateLocation.value = Math.min(0, location)
    }
    else {
      location = tabsTranlateLocation.value - widthStep * 2
      tabsTranlateLocation.value = Math.max(maxMoveDistance.value, location)
    }
    tabsRef.value!.style.left = `${tabsTranlateLocation.value}px`
  }

  // 设置当前选中的tab class
  const setActiveClass = (tab: TabType) => {
    let isActive = false
    if (route.value) {
      isActive
        = activePath.value.includes(tab.path)
          || (!!tab.meta?.activeMenu
            && tab.meta.activeMenu === route.value?.meta?.activeMenu)
    }
    else {
      isActive = activePath.value.includes(tab.path)
    }
    return isActive ? 'tab-active' : null
  }

  // 超出区域后移动
  const moveTab = (path: string[]) => {
    if (!tabsRef.value)
      return
    const index = tabs.value.findIndex((per: TabType) =>
      path.includes(per.path),
    )
    if (index > -1) {
      const locationRight = (index + 1) * widthStep
      const locationLeft = index * widthStep
      if (locationRight + tabsTranlateLocation.value > tabsOutWidth.value) {
        tabsTranlateLocation.value = Math.max(
          maxMoveDistance.value,
          tabsOutWidth.value - locationRight - 46,
        )
      }
      else if (
        locationLeft - widthStep * 2 + tabsTranlateLocation.value
        < 0
      ) {
        tabsTranlateLocation.value = Math.min(0, -locationLeft + widthStep * 2)
      }
      tabsRef.value.style.left = `${tabsTranlateLocation.value}px`
    }
  }
  // tab删除
  const handleDel = async (tab: TabType, index: number) => {
    tabs.value.splice(index, 1)
    emit('removeTabs', [tab])
    const tabLength = tabs.value.length
    let curActive
    if (tabLength === 0) {
      curActive = defaultTab
    }
    else if (activePath.value.includes(tab.path)) {
      const nextIndex = Math.max(0, index - 1)
      curActive = tabs.value[nextIndex]
    }
    // eslint-disable-next-line ts/no-unused-expressions
    curActive && tabItemClick(curActive)
    emit('updateTabs', tabs.value)
    await nextTick(calculateValue)
  }

  const deleteByPath = (path: string) => {
    const index = tabs.value.findIndex((per: TabType) => per.path === path)
    if (index > -1) {
      handleDel(tabs.value[index], index)
    }
    else {
      console.warn('cannot found any tab by path')
    }
  }
  onMounted(() => {
    if (tabsOutRef.value) {
      tabsOutWidth.value = tabsOutRef.value.clientWidth
    }
  })
  watch(
    () => tabs.value,
    (nVal) => {
      if (nVal?.length) {
        setTimeout(() => {
          calculateValue()
        })
      }
    },
    {
      immediate: true,
    },
  )
  watch(
    () => route.value,
    (nVal) => {
      if (nVal) {
        activePath.value = [nVal.fullPath, nVal.path]
        setTimeout(() => {
          calculateValue()
          moveTab(activePath.value)
        }, 50)
      }
    },
    { immediate: true, deep: true },
  )

  return {
    tabsTranlateLocation,
    maxMoveDistance,
    setActiveClass,
    tabsRef,
    tabsOutRef,
    canMove,
    translateX,
    tabItemClick,
    handleDel,
    closeAllTab,
    deleteByPath,
  }
}
export default useBar
